package com.seeTools.boot.pc.service.sys.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.seeTools.boot.api.bo.sys.LoginRequest;
import com.seeTools.boot.api.entity.sys.SysRole;
import com.seeTools.boot.api.entity.sys.SysTenant;
import com.seeTools.boot.api.entity.sys.SysTokenInfo;
import com.seeTools.boot.api.entity.sys.SysUser;
import com.seeTools.boot.common.constant.Constants;
import com.seeTools.boot.common.core.ServiceException;
import com.seeTools.boot.common.tools.ip.IpUtils;
import com.seeTools.boot.pc.conf.ThreadLocalHolder;
import com.seeTools.boot.pc.service.sys.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 系统登录 服务实现类
 *
 * @author xiaotong
 */
@Slf4j
@Service
public class SysLoginServiceImpl implements ISysLoginService {

    @Resource
    private ISysUserService iSysUserService;

    @Resource
    private ISysRoleService iSysRoleService;

    @Resource
    private ISysMenuService iSysMenuService;

    @Resource
    private ISysTenantService iSysTenantService;


    /**
     * 获取token
     *
     * @return
     */
    @Override
    public SysTokenInfo getToken() {
        // 先查看是否有token
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        SysTokenInfo sysTokenInfo = new SysTokenInfo();
        if (!tokenInfo.isLogin) {
            SysUser sysUser = iSysUserService.findOne(SysUser::getLoginName, Constants.ADMIN_LOGIN_NAME);
            if (ObjectUtil.isNotEmpty(sysUser)) {
                String device = sysUser.getLoginName() + "@pc";
                StpUtil.login(sysUser.getId(), device);
                tokenInfo = StpUtil.getTokenInfo();
                sysTokenInfo.setTokenValue(tokenInfo.getTokenValue());
                sysTokenInfo.setTokenName(tokenInfo.getTokenName());
                // 刷新最近登录时间
                iSysUserService.updateLastLoginTime(sysUser.getId(), device);
            }
        } else {
            sysTokenInfo.setTokenValue(tokenInfo.getTokenValue());
            sysTokenInfo.setTokenName(tokenInfo.getTokenName());
        }

        return sysTokenInfo;
    }


    @Override
    public SysUser login(LoginRequest loginRequest, String loginType) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysUser::getLoginName, loginRequest.getLoginName())
                .eq(SysUser::getPassword, loginRequest.getPassword());
        List<SysUser> userList = iSysUserService.list(queryWrapper);
        if (!userList.isEmpty()) {
            SysUser user = userList.get(0);
            if (user.getExpirationDate() != null && !user.getExpirationDate().isAfter(LocalDateTime.now())) {
                throw new ServiceException("该账户的有效截止日已到期，请联系管理员！");
            }
            if (user.getActive() == 0) {
                throw new ServiceException("该账户处于禁用状态，请联系管理员！");
            }
            Long tenantId = user.getTenantId();
            Long userId = user.getId();
            String device = user.getLoginName() + loginType;
            StpUtil.login(userId, device);
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            user.setTokenName(tokenInfo.getTokenName());
            user.setTokenValue(tokenInfo.getTokenValue());
            ThreadLocalHolder.setTenantId(tenantId);
            StpUtil.getSession().set("tenantId", tenantId);
            // 刷新最近登录时间
            iSysUserService.updateLastLoginTime(userId, device);
            // 记录登入日志
            recordLoginInfo(user.getId());
            return user;
        }
        return null;
    }

    @Override
    public SysUser login(LoginRequest loginRequest) {
        return login(loginRequest, "@pc");
    }

    @Override
    public void logout() {
        long userId = getLoginUserId();
        log.info("@logout#id={}", userId);
        StpUtil.logout();
    }

    @Override
    public SysUser getUserInfo() {
        long userId = getLoginUserId();
        SysUser user = iSysUserService.getById(userId);
        List<SysRole> roleList = iSysRoleService.getRoleListByUserId(userId);
        user.setRoles(roleList);
        List<String> authBtnList = iSysMenuService.getUserAuthBtnList(userId);
        user.setAuthBtnList(authBtnList);
        SysTenant tenant = iSysTenantService.findByTenantIdCache(user.getTenantId());
        user.setTenantName(tenant != null ? tenant.getTenantName() : "");
        return user;
    }

    @Override
    public Long getLoginTenantId() {
        return ThreadLocalHolder.getTenantId();
    }

    @Override
    public Long getLoginUserId() {
        return StpUtil.getLoginIdAsLong();
    }

    public void recordLoginInfo(Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setId(userId);
        sysUser.setLastLoginIp(IpUtils.getIpAddr());
        sysUser.setLastLoginTime(DateUtil.date().toLocalDateTime());
        iSysUserService.updateById(sysUser);
    }
}
